import * as request from 'supertest'
import {
  GiftState,
  MailModel,
  MailState,
  MailType,
  PublicMailModel,
  PublicMailRecordModel
} from "../../database/models/mail";
import {PlayerModel} from "../../database/models/player";
import app from "../../serverApp";
import {testPublicMail} from "../initData/data";
import {expect, setupTestEnv, tearDownTestEnv, TestEnv} from "./helper";

describe('邮件', () => {

  let env: TestEnv = null
  let player = null
  let publicMail = null
  let mail = null
  before(async () => {
    env = await setupTestEnv()

    player = env.player
  })

  after(async () => {
    await tearDownTestEnv()
  })
  beforeEach(async () => {
    publicMail = await PublicMailModel.create(testPublicMail)

    mail = await MailModel.create({
      title: `特别送你这个邮件`,
      content: `先阅读，后领奖，再删不删随你`,
      to: player.id,
      type: MailType.GIFT,
      gift: {coin: 5, freeCoin: 6, gem: 7, point: 8}
    })
  })

  afterEach(async () => {
    await MailModel.deleteMany({})
    await PublicMailRecordModel.deleteMany({})
  })

  it('获取所有邮件', async () => {
    let mails = null
    await request(app)
      .get(`/mail/get/all`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        mails = res.body.data.mails
      })
    expect(mails.length).to.equal(2)

  })
  it('一键阅读所有mail邮件', async () => {

    await request(app)
      .put(`/mail/read/allMail`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })

    const mails = await MailModel.find({to: player.id})
    mails.forEach(m => expect(m.state).to.equal(MailState.READ))
  })

  it('阅读一个mail邮件 领奖（如果AVAILABLE） 再删除', async () => {

    await request(app)
      .put(`/mail/read/mail/${mail._id}`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })
    const mail0 = await MailModel.findById(mail._id)
    expect(mail0.state).to.equal(MailState.READ)

    const p0 = await PlayerModel.findById(player.id)
    await request(app)
      .put(`/mail/requestGift/mail/${mail._id}`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })
    const p1 = await PlayerModel.findById(player.id)
    expect(p1.coin).to.equal(p0.coin + mail.gift.coin)
    expect(p1.freeCoin).to.equal(p0.freeCoin + mail.gift.freeCoin)
    expect(p1.gem).to.equal(p0.gem + mail.gift.gem)
    expect(p1.point).to.equal(p0.point + mail.gift.point)
    const mail2 = await MailModel.findById(mail._id)
    expect(mail2.giftState).to.equal(GiftState.REQUESTED)

    await request(app)
      .delete(`/mail/delete/mail/${mail._id}`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })
    const mail3 = await MailModel.findById(mail._id)
    expect(mail3).to.equal(null)
  })

  it('阅读一个公告（public）邮件 领奖（如果AVAILABLE） 再删除 ', async () => {
    await request(app)
      .put(`/mail/read/public/${publicMail._id}`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })
    const mail0 = await PublicMailRecordModel.findOne({mail: publicMail._id})
    expect(mail0.state).to.equal(MailState.READ)

    const p0 = await PlayerModel.findById(player.id)
    await request(app)
      .put(`/mail/requestGift/public/${publicMail._id}`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })
    const p1 = await PlayerModel.findById(player.id)
    expect(p1.coin).to.equal(p0.coin + publicMail.gift.coin)
    expect(p1.freeCoin).to.equal(p0.freeCoin + publicMail.gift.freeCoin)
    expect(p1.gem).to.equal(p0.gem + publicMail.gift.gem)
    expect(p1.point).to.equal(p0.point + publicMail.gift.point)
    const mail1 = await PublicMailRecordModel.findOne({player: player.id, mail: publicMail._id})
    expect(mail1.giftState).to.equal(GiftState.REQUESTED)

    await request(app)
      .delete(`/mail/delete/public/${publicMail._id}`)
      .set({'x-jwt': env.jwt})
      .then(res => {
        expect(res.body).to.have.properties({
          ok: true
        })
      })
    const mail2 = await PublicMailRecordModel.findOne({player: player.id, mail: publicMail._id})
    expect(mail2.state).to.equal(MailState.DELETE)
  })

})
